package com.snopy.concurrency.rwlock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author snopy
 * @version 1.0.0
 * @classname RWLockDemo
 * @description
 * @email 77912204@qq.com
 * @date 2022/06/29 20:18
 */
@Slf4j
public class RWLockDemo {

    public static void main(String[] args) throws InterruptedException {
        DataContainer data = new DataContainer("hello world!");
        Thread t1 = new Thread(() -> {
            log.debug("t1...");
           data.write();
        }, "t1");
        Thread t2 = new Thread(() -> {
            log.debug("t2...");
            data.write();
        }, "t2");
        t1.start();
        TimeUnit.NANOSECONDS.sleep(1);
        t2.start();
    }
}
@Slf4j
class DataContainer{
    ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    ReentrantReadWriteLock.ReadLock r = rwLock.readLock();
    ReentrantReadWriteLock.WriteLock w = rwLock.writeLock();

    public DataContainer(Object data) {
        this.data = data;
    }

    private final Object data;
    public Object read(){
        String name = Thread.currentThread().getName();
        log.debug("thread {}:r locking...",name);
        r.lock();
        log.debug("thread {}:r locked...",name);
        try {
            log.debug("thread {}:read...",name);
            TimeUnit.SECONDS.sleep(1);
            return data;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log.debug("thread {}:r unlocking...",name);
            r.unlock();
        }
        return null;
    }
    public void write(){
        String name = Thread.currentThread().getName();
        log.debug("thread {}:w locking...",name);
        w.lock();
        log.debug("thread {}:w locked...",name);
        try{
            log.debug("thread {}:write...",name);
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log.debug("thread {}:w unlocking...",name);
            w.unlock();
        }
    }
}